"""
SSL 证书数据模型
用于 SSL Automation Center (SAC)
"""
from pydantic import BaseModel, Field, field_validator
from typing import Optional, List
from datetime import datetime, timedelta
from enum import Enum


class CAProvider(str, Enum):
    """CA 提供商"""
    LETSENCRYPT = "letsencrypt"
    ZEROSSL = "zerossl"


class CertificateStatus(str, Enum):
    """证书状态"""
    PENDING = "pending"      # 待处理
    ISSUED = "issued"        # 已签发
    EXPIRED = "expired"      # 已过期
    REVOKED = "revoked"      # 已吊销
    FAILED = "failed"        # 申请失败


class DNSValidationType(str, Enum):
    """DNS 验证类型"""
    DNS_01_AUTO = "dns-01-auto"      # 自动 DNS 验证
    DNS_01_MANUAL = "dns-01-manual"  # 手动 DNS 验证


class DownloadFormat(str, Enum):
    """证书下载格式"""
    PEM = "pem"
    ZIP = "zip"
    PFX = "pfx"


class CertificateBase(BaseModel):
    """证书基础模型"""
    domain: str = Field(..., description="主域名", min_length=1, max_length=253)
    sans: List[str] = Field(default_factory=list, description="扩展域名列表", max_items=100)
    ca_provider: CAProvider = Field(default=CAProvider.LETSENCRYPT, description="CA 提供商")
    dns_credential_id: Optional[str] = Field(None, description="DNS 凭据 ID")
    auto_renew: bool = Field(default=True, description="是否自动续签")
    
    @field_validator('domain')
    @classmethod
    def validate_domain(cls, v: str) -> str:
        """验证域名格式"""
        import re
        
        # 基本格式检查
        if not v or len(v) > 253:
            raise ValueError("域名长度必须在 1-253 字符之间")
        
        # 检查连续点号
        if '..' in v:
            raise ValueError("域名不能包含连续点号")
        
        # 检查每个段
        parts = v.split('.')
        for part in parts:
            if not part or len(part) > 63:
                raise ValueError("域名每段长度必须在 1-63 字符之间")
            
            # 允许通配符
            if part != '*' and not re.match(r'^[a-z0-9-_]+$', part, re.IGNORECASE):
                raise ValueError(f"域名段 '{part}' 包含非法字符")
            
            if part.startswith('-') or part.endswith('-'):
                raise ValueError(f"域名段 '{part}' 不能以 - 开头或结尾")
        
        return v.lower()
    
    @field_validator('sans')
    @classmethod
    def validate_sans(cls, v: List[str]) -> List[str]:
        """验证扩展域名"""
        if len(v) > 100:
            raise ValueError("SAN 域名不能超过 100 个")
        
        # 验证每个 SAN 域名
        validated = []
        for domain in v:
            # 使用相同的域名验证逻辑
            validated.append(cls.validate_domain(domain))
        
        return validated


class CertificateCreate(CertificateBase):
    """创建证书请求"""
    validation_type: DNSValidationType = Field(
        default=DNSValidationType.DNS_01_AUTO,
        description="DNS 验证类型"
    )
    contact_email: str = Field(..., description="联系邮箱")


class CertificateInDB(CertificateBase):
    """数据库中的证书"""
    id: str
    user_id: str = Field(..., description="用户 ID")
    status: CertificateStatus = Field(default=CertificateStatus.PENDING, description="证书状态")
    
    # 证书内容（加密存储）
    cert_fullchain_pem: Optional[str] = Field(None, description="证书链 PEM")
    key_encrypted: Optional[str] = Field(None, description="AES-256 加密的私钥")
    
    # 时间字段
    expires_at: Optional[datetime] = Field(None, description="证书过期时间")
    issued_at: Optional[datetime] = Field(None, description="签发时间")
    ttl_deletion_at: Optional[datetime] = Field(None, description="TTL 删除时间（过期 + 732 天）")
    deleted_at: Optional[datetime] = Field(None, description="软删除时间")
    created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
    updated_at: Optional[datetime] = Field(None, description="更新时间")
    
    # DNS 验证信息
    dns_validation_records: Optional[List[dict]] = Field(
        default_factory=list,
        description="DNS 验证记录"
    )
    
    class Config:
        from_attributes = True
    
    def calculate_ttl_deletion(self) -> Optional[datetime]:
        """计算 TTL 删除时间"""
        if self.expires_at and not self.auto_renew:
            return self.expires_at + timedelta(days=732)
        return None


class CertificateOut(CertificateBase):
    """返回的证书信息（不含私钥）"""
    id: str
    user_id: str
    status: CertificateStatus
    expires_at: Optional[datetime]
    issued_at: Optional[datetime]
    created_at: datetime
    updated_at: Optional[datetime]
    
    # 证书链（公开）
    cert_fullchain_pem: Optional[str] = None
    
    # 是否有私钥（但不返回私钥内容）
    has_private_key: bool = False
    
    class Config:
        from_attributes = True


class CertificateDetail(CertificateOut):
    """证书详情（可选返回私钥）"""
    key_pem: Optional[str] = Field(None, description="私钥 PEM（需要特殊权限）")
    dns_validation_records: Optional[List[dict]] = None


class CertificateUpdate(BaseModel):
    """更新证书"""
    auto_renew: Optional[bool] = None
    status: Optional[CertificateStatus] = None


class ListCertificatesQuery(BaseModel):
    """证书列表查询"""
    domain: Optional[str] = Field(None, description="按域名过滤")
    status: Optional[CertificateStatus] = Field(None, description="按状态过滤")
    ca_provider: Optional[CAProvider] = Field(None, description="按 CA 提供商过滤")
    auto_renew: Optional[bool] = Field(None, description="按自动续签过滤")
    skip: int = Field(default=0, ge=0, description="跳过记录数")
    limit: int = Field(default=20, ge=1, le=100, description="返回记录数")


class DNSValidationRecord(BaseModel):
    """DNS 验证记录"""
    domain: str = Field(..., description="需要验证的域名")
    record_name: str = Field(..., description="DNS 记录名称，如 _acme-challenge.example.com")
    record_type: str = Field(default="TXT", description="记录类型")
    record_value: str = Field(..., description="记录值")
    validated: bool = Field(default=False, description="是否已验证")


class CertificateDownloadRequest(BaseModel):
    """证书下载请求"""
    certificate_id: str = Field(..., description="证书 ID")
    format: DownloadFormat = Field(default=DownloadFormat.PEM, description="下载格式")
    include_private_key: bool = Field(default=True, description="是否包含私钥")


class RenewCertificateRequest(BaseModel):
    """续签证书请求"""
    certificate_id: str = Field(..., description="证书 ID")
    force: bool = Field(default=False, description="强制续签（即使未过期）")


class SubmitDNSValidationRequest(BaseModel):
    """提交 DNS 验证请求"""
    certificate_id: str = Field(..., description="证书 ID")
    domain: Optional[str] = Field(None, description="指定验证的域名（可选）")

